package com.cloudbroker.bcs.common.validatioin.aspect;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import com.alibaba.fastjson.JSONObject;
import com.cloudbroker.bcs.common.constants.BasicErrorCodes;
import com.cloudbroker.bcs.common.constants.BasicFields;
import com.cloudbroker.bcs.common.entity.Error;
import com.cloudbroker.bcs.common.entity.HSBCPSBackVO;
import com.cloudbroker.bcs.common.util.PrintUtil;
import com.cloudbroker.bcs.common.util.ReflectionUtil;
import com.cloudbroker.bcs.common.util.VOUtil;
import com.cloudbroker.bcs.common.validatioin.ValidateUtil;
import com.cloudbroker.bcs.common.vo.HSBCSVO;

public class ValidateAspect {
    
    private static final String CLASS_NAME = ValidateAspect.class.getName();
    
    private static final Logger LOGGER = LoggerFactory.getLogger(CLASS_NAME);
    
    public ValidateAspect() {
        PrintUtil.printComponentLoaded(LOGGER, CLASS_NAME);
    }
    
    public Object validateParam(ProceedingJoinPoint pjp) throws Throwable {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Class<?> returnType = signature.getReturnType();
        for (Object arg : pjp.getArgs()) {
            if (arg instanceof HSBCSVO) {
                List<Map<String, Object>> violationsStructure = ValidateUtil.validOrReturnViolationsStructure(arg);
                if (null != violationsStructure) {
                    if( ReflectionUtil.isSubClass(returnType , HSBCPSBackVO.class) ) {
                        return createErrorInfosInHsbcps(violationsStructure , returnType);
                    } else if( ReflectionUtil.isSubClass(returnType , Map.class) ) {
                        return createErrorInfosInMap(violationsStructure);
                    }
                }
            } else {
                // ignore;
            }
        }
        
        return pjp.proceed();
    }

    private String getErrorInfoFromViolationsStructure(List<Map<String,Object>> violationsStructure) {
        StringBuffer sb = new StringBuffer();
        for (Map<String, Object> map : violationsStructure) {
            Object info = map.get(BasicFields.ERROR_INFO);
            Object field = map.get(BasicFields.ERROR_ON);
            if (info != null && field != null) {
                sb.append(field);
                sb.append(info);
                sb.append(",");
            }
        }
        if( sb.length() > 0 ) {
            return sb.deleteCharAt(sb.length()-1).toString();
        }
        return sb.toString();
    }

    private Object createErrorInfosInHsbcps(List<Map<String, Object>> violationsStructure , Class<?> returnType) {
        HSBCPSBackVO form = (HSBCPSBackVO)BeanUtils.instantiate(returnType);
        List<Error> errors = new ArrayList<>();
        for(Map<String,Object> violation : violationsStructure) {
            errors.add(JSONObject.parseObject(JSONObject.toJSONString(violation) , Error.class));
        }
        form.setErrors(errors);
        form.setError_info(getErrorInfoFromViolationsStructure(violationsStructure));
        form.setError_no(BasicErrorCodes.PARAM_ERROR);
        return form;
    }

    private Object createErrorInfosInMap(List<Map<String, Object>> violationsStructure) {
        Map<String, Object> result = VOUtil.genEmptyResult();
        result.put(BasicFields.ERROR_INFO, getErrorInfoFromViolationsStructure(violationsStructure));
        return VOUtil.setErrorResult(result, BasicErrorCodes.PARAM_ERROR);
    }

}
